package com.xiaoshuidi.cloud.module.iot.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.xiaoshuidi.cloud.framework.tenant.core.aop.TenantIgnore;
import com.xiaoshuidi.cloud.module.iot.common.ResultModel;
import com.xiaoshuidi.cloud.module.iot.dal.model.AccessTokenRequestWrapperModel;
import com.xiaoshuidi.cloud.module.iot.dal.model.AccessTokenResponseWrapperModel;
import com.xiaoshuidi.cloud.module.iot.dal.model.account.AddThirdApiAccountVo;
import com.xiaoshuidi.cloud.module.iot.dal.model.account.CategorysByBrandVo;
import com.xiaoshuidi.cloud.module.iot.dal.pojo.TbAccountDo;
import com.xiaoshuidi.cloud.module.iot.dal.pojo.TbDeviceDo;
import com.xiaoshuidi.cloud.module.iot.dal.repository.DeviceRepository;
import com.xiaoshuidi.cloud.module.iot.dal.repository.TbAccountRepository;
import com.xiaoshuidi.cloud.module.iot.dal.repository.TbBrandRepository;
import com.xiaoshuidi.cloud.module.iot.enums.ErrorCodeEnum;
import com.xiaoshuidi.cloud.module.iot.framework.ThreadPoolConfig.ThreadExecutePool;
import com.xiaoshuidi.cloud.module.iot.service.LocalAccessTokenServcie;
import com.xiaoshuidi.cloud.module.iot.service.LocalDeviceService;
import com.xiaoshuidi.cloud.module.iot.service.MeChantAccountService;
import com.xiaoshuidi.cloud.module.iot.uitils.UUidUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Sky
 * create 2019/05/22
 * email sky.li@ixiaoshuidi.com
 **/
@Service
public class MeChantAccountServiceImpl implements MeChantAccountService {

    private static final Logger LOGGER = LoggerFactory.getLogger(MeChantAccountServiceImpl.class);

    @Autowired
    private TbBrandRepository tbBrandDataAccess;

    @Autowired
    private TbAccountRepository tbAccountDataAccess;

    @Autowired
    private LocalAccessTokenServcie accessTokenFeginService;

    @Autowired
    private ThreadExecutePool threadExecutePool;

    @Autowired
    private LocalDeviceService localDeviceService;

    @Autowired
    private DeviceRepository deviceDataAccess;

    /**
     * 根据品牌编号查询该品牌对接品类
     *
     * @param brandNo
     * @return
     */
    @Override
    public ResultModel<List<CategorysByBrandVo>> getCategoryByBrand(String brandNo) {
        List<CategorysByBrandVo> categorysByBrandVos = tbBrandDataAccess.getCategoryByBrand(brandNo);
        return ResultModel.createSuccess(categorysByBrandVos);
    }

    /**
     * 添加品牌对应的第三方API账号
     *
     * @param tbAccountDo
     * @return
     */
    @Override
    public ResultModel<AddThirdApiAccountVo> addThirdApiAccount(TbAccountDo tbAccountDo) throws Exception {
        LOGGER.info("account->添加品牌对应的第三方API账号,用户填写账号信息:{}", JSONObject.toJSONString(tbAccountDo));
        ResultModel<AddThirdApiAccountVo> addThirdApiAccountVoResultModel = null;
        AddThirdApiAccountVo addThirdApiAccountVo = new AddThirdApiAccountVo();
        //根据品牌编号brand_no，API账号login_name,API密钥login_key查询是否有该条记录
        LOGGER.info("account->记录#########################");
        TbAccountDo account = tbAccountDataAccess.getTbAccountByBnAndLnAndLk(tbAccountDo);
        LOGGER.info("account->记录$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
        if (account != null) {
            LOGGER.info("account->记录#########################" + JSONObject.toJSONString(account));
            addThirdApiAccountVoResultModel = ResultModel.createFail(ErrorCodeEnum.REPEAT_ADD_API.getCode(), ErrorCodeEnum.REPEAT_ADD_API.getMsg());
            addThirdApiAccountVo.setApiNo(account.getApiNo());
            addThirdApiAccountVoResultModel.setData(addThirdApiAccountVo);
        } else {
            LOGGER.info("account->记录$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" + JSONObject.toJSONString(account));
            AccessTokenRequestWrapperModel accessTokenRequestWrapperModel = new AccessTokenRequestWrapperModel();
            accessTokenRequestWrapperModel.setBrand(tbAccountDo.getBrandNo());
            accessTokenRequestWrapperModel.setAppId(tbAccountDo.getLoginName());
            accessTokenRequestWrapperModel.setAppKey(tbAccountDo.getLoginKey());
            ResultModel<AccessTokenResponseWrapperModel> accessTokenResultModel = accessTokenFeginService.refreshAccessToken(accessTokenRequestWrapperModel);
            LOGGER.info("account->添加品牌对应的第三方API账号,验证login_name,login_key有效性:{}", JSONObject.toJSONString(accessTokenResultModel));
            if (ResultModel.CODE_SUCCESS.equals(accessTokenResultModel.getCode())) {
                AccessTokenResponseWrapperModel accessTokenData = accessTokenResultModel.getData();
                String apiNo = UUidUtils.generateUuid();
                tbAccountDo.setApiNo(apiNo);
                String brandName = tbBrandDataAccess.getCategoryByBrand(tbAccountDo.getBrandNo()).get(0).getBrandName();
                tbAccountDo.setBrandName(brandName);
                tbAccountDataAccess.save(tbAccountDo);
                addThirdApiAccountVo.setApiNo(apiNo);
                addThirdApiAccountVoResultModel = ResultModel.createSuccess(addThirdApiAccountVo);
                //调用Biz拉取设备并入库(多线程)

                threadExecutePool.getExecutor().execute(() -> {
                    List<TbAccountDo> list = new ArrayList<>();
                    list.add(tbAccountDo);
                    ResultModel resultModel = null;
                    try {
                        resultModel = localDeviceService.saveDeviceListToIOTByLnLk(list);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                    LOGGER.info("account->添加品牌对应的第三方API账号,调用Biz拉取设备并入库(多线程),结果:{}", JSONObject.toJSONString(resultModel));
                });
            } else {
                addThirdApiAccountVoResultModel = ResultModel.createFail(ErrorCodeEnum.INVALID_API_NO.getCode(), ErrorCodeEnum.INVALID_API_NO.getMsg());
            }
        }
        return addThirdApiAccountVoResultModel;
    }

    /**
     * 根据apiNo查询tb_account记录
     *
     * @param apiNo
     * @return
     */
    @Override
    public ResultModel<TbAccountDo> getThirdApiByApiNo(String apiNo) {
        TbAccountDo tbAccountModel = tbAccountDataAccess.getThirdApiByApiNo(apiNo);
        return ResultModel.createSuccess(tbAccountModel);
    }

    /**
     * 删除品牌对应的第三方API账号
     *
     * @param tbAccountDo
     * @return
     */
    @Override
    public ResultModel deleteThirdApiAccount(TbAccountDo tbAccountDo) {
        LOGGER.info("account->删除品牌对应的第三方API账号,请求内容:{}", JSONObject.toJSONString(tbAccountDo));
        ResultModel resultModel = null;
        TbAccountDo tbAccountData = tbAccountDataAccess.getThirdApiByApiNo(tbAccountDo.getApiNo());
        if (tbAccountData == null) {
            resultModel = ResultModel.createFail(ErrorCodeEnum.INVALID_API_NO.getCode(), ErrorCodeEnum.INVALID_API_NO.getMsg());
        } else {
            //查询该Api账号是否关联设备
            List<TbDeviceDo> tbDeviceModelList = deviceDataAccess.getDeviceListByOneApiNo(tbAccountDo.getApiNo());
            if (tbDeviceModelList != null && tbDeviceModelList.size() != 0) {
                resultModel = ResultModel.createFail(ErrorCodeEnum.APINO_HADBIND_DEVICE_REFUSE_DELETE.getCode(), ErrorCodeEnum.APINO_HADBIND_DEVICE_REFUSE_DELETE.getMsg());
            } else {
                boolean deleteResult = tbAccountDataAccess.deleteTbAccountRecord(tbAccountDo.getApiNo());
                LOGGER.info("account->数据库删除对应API_no,返回结果:{}", deleteResult);
                resultModel = ResultModel.createSuccess();
            }
        }
        return resultModel;
    }

    /**
     * 编辑品牌对应的第三方API账号
     *
     * @param tbAccountDo
     * @return
     */
    @Override
    public ResultModel updateThirdApiAccount(TbAccountDo tbAccountDo) throws Exception {
        LOGGER.info("account->编辑品牌对应的第三方API账号,请求内容:{}", JSONObject.toJSONString(tbAccountDo));
        ResultModel resultModel = null;
        TbAccountDo tbAccountData = tbAccountDataAccess.getThirdApiByApiNo(tbAccountDo.getApiNo());
        if (tbAccountData == null) {
            resultModel = ResultModel.createFail(ErrorCodeEnum.INVALID_API_NO.getCode(), ErrorCodeEnum.INVALID_API_NO.getMsg());
        } else {
            //验证修改后的账号的有效性
            AccessTokenRequestWrapperModel accessTokenRequestWrapperModel = new AccessTokenRequestWrapperModel();
            accessTokenRequestWrapperModel.setBrand(tbAccountData.getBrandNo());
            accessTokenRequestWrapperModel.setAppId(tbAccountDo.getLoginName());
            accessTokenRequestWrapperModel.setAppKey(tbAccountDo.getLoginKey());
            ResultModel<AccessTokenResponseWrapperModel> accessTokenResultModel = accessTokenFeginService.getAccessToken(accessTokenRequestWrapperModel);
            LOGGER.info("account->编辑品牌对应的第三方API账号,验证login_name,login_key有效性:{}", JSONObject.toJSONString(accessTokenResultModel));
            if (ResultModel.CODE_SUCCESS.equals(accessTokenResultModel.getCode())) {
                if (StrUtil.isNotBlank(tbAccountDo.getLoginName())) {
                    tbAccountData.setLoginName(tbAccountDo.getLoginName());
                }
                if (StrUtil.isNotBlank(tbAccountDo.getLoginKey())) {
                    tbAccountData.setLoginKey(tbAccountDo.getLoginKey());
                }
                if (StrUtil.isNotBlank(tbAccountDo.getLoginMobile())) {
                    tbAccountData.setLoginMobile(tbAccountDo.getLoginMobile());
                }
                boolean updateResult = tbAccountDataAccess.updateById(tbAccountData);
                LOGGER.info("account->数据库编辑品牌对应的第三方API账号结果:{}", updateResult);
                resultModel = ResultModel.createSuccess();
            } else {
                resultModel = ResultModel.createFail(ErrorCodeEnum.INVALID_API_NO.getCode(), ErrorCodeEnum.INVALID_API_NO.getMsg());
            }
        }
        return resultModel;
    }

    @Override
    public List<String> getApiNosByUserId() {
        List<String> apiNos = tbAccountDataAccess.getApiNosByUserId();
        return apiNos;
    }

    /**
     * 获取设备平台账号
     *
     * @param userId
     * @return
     */
    @Override
    public ResultModel<PageInfo<TbAccountDo>> getDeviceAccount(Long userId, Integer pageSize, Integer pageNum) {
        ResultModel<PageInfo<TbAccountDo>> resultModel = tbAccountDataAccess.getDeviceAccount(userId, pageSize, pageNum);
        return resultModel;
    }
}
